package firbi.base;

import java.util.ArrayList;
import java.util.HashMap;

import android.app.Dialog;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TabHost;
import android.widget.TextView;
import android.widget.TabHost.TabSpec;
import firbi.base.com.BusRoute;
import firbi.base.util.Constants;

/**
 * DesinationView takes in a bus route id and displays the destinations for that route,
 * passing back to the caller the destination the user selected.
 * 
 * The activity requires that an int be passed in the intent under the key "bus_route_id".
 * This key should correspond an id for a BusRoute.
 * @author Kathryn Winglee
 *
 */

public class DestinationView extends ListActivity {	
	private BusRoute mRoute;//BusRoute for the view
	private String[][] mDest;//the destinations for this route
	private ArrayList<HashMap<String,String>> mList = new ArrayList<HashMap<String,String>>();//list displayed in ListView
	private ProgressDialog mProgressD;//the progress display
	private Dialog mHelpD;//the dialog box for help
	private static boolean dialogOn = true;//true if the dialog should be displayed
	private static boolean threadDone=true;//true if the thread is done.

	/* Methods for the life cycle*/
	/**
	 * Called when the DestinationView is first created.
	 * Sets up the UI and gets the destinations.
	 * 
	 * @param savedInstanceState	data used if the activity is being re-initialized
	 */
	@Override
	public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
		Bundle extras = getIntent().getExtras();
        if (extras != null && extras.containsKey(Constants.sROUTE_KEY)) {
        	String id = (String) extras.get(Constants.sROUTE_KEY);
        	mRoute = BusRoute.find(id);
        } else {
            Intent intent = new Intent();
            intent.putExtra(Constants.sDEST_KEY, "");
            setResult(RESULT_CANCELED);
            finish();
        }
        if(mRoute == null) {
            Intent intent = new Intent();
            intent.putExtra(Constants.sDEST_KEY, "");
            setResult(RESULT_CANCELED);
            finish();
        } else {
        	setContentView(R.layout.destinationview);
        	TextView routeLabel = (TextView) findViewById(R.id.routeNumber);
        	routeLabel.setText(mRoute.getRouteNumber());
        	setUpHelp();
        	getDestinations();
        	registerForContextMenu(getListView());
        }
	}
	
	/**
	 * Used to save the state so the activity can be restored to the current state if
	 * another activity comes back to it before it is killed
	 * 
	 * @param savedInstanceState	Bundle that stores the saved state
	 */
	@Override
	public void onSaveInstanceState(Bundle savedInstanceState) {
		savedInstanceState.putString(Constants.sROUTE_KEY, mRoute.getId());
		super.onSaveInstanceState(savedInstanceState);    	
	}

	/**
	 * When a user clicks on one of the destinations, puts the chosen destination
	 * in an intent and ends the activity.
	 * 
	 * @param l			the ListView clicked on 
	 * @param v			the view clicked on within the list
	 * @param position	position of v in the list
	 * @param id		row id of the item clicked
	 */
	@SuppressWarnings("unchecked")
	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		// Log.d(DEST_KEY, "onListItemClick start");
	    super.onListItemClick(l, v, position, id);
	    HashMap<String,String> d = (HashMap<String, String>) l.getItemAtPosition(position);
	    String dest = d.get("dest");
		 Log.d(Constants.sDEST_KEY, dest);
	    Intent intent = new Intent();
	    intent.putExtra(Constants.sDEST_KEY, dest);
	    setResult(RESULT_OK, intent);
	    finish();
	}

	/**
	 * Initializes the menu
	 * 
	 * @param menu		the menu to put items in
	 * @return true if the menu is to be displayed; false to not show the menu
	 */
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
	    inflater.inflate(R.menu.destinationview_menu, menu);
	    return true;
	}

	/**
	 * Called when one of the items in the menu is clicked on
	 * 
	 * @param item  item in the menu selected
	 * @return  true if the menu is to be displayed; false to not show the menu
	 */
	public boolean onOptionsItemSelected(MenuItem item) {
		Intent i;
	    switch (item.getItemId()) {
			case R.id.menu_item_mapsearch:
				i = new Intent(this, Search.class);
				i.putExtra("isMapView", true);
				startActivity(i);
				return true;
			case R.id.menu_item_listsearch:
				i = new Intent(this, Search.class);
				i.putExtra("isMapView", false);
				startActivity(i);
				return true;
			case R.id.menu_item_favs://go to the favorites view
				i = new Intent(this, Favorites.class);
				startActivity(i);
				return true;
			case R.id.menu_item_help:
				mHelpD.show();
				return true;
		}
	    return false;
	}

	/**
	 * Called when one of the keys is pushed.
	 * The back button is overwritten to send back a blank Destination.
	 * All other buttons call super and perform the default functions.
	 * 
	 * @param keyCode	the key pushed
	 * @param ev		description of the key event
	 * @return false if event not handled, true otherwise
	 */
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent ev) {
		switch(keyCode) {
		case KeyEvent.KEYCODE_BACK:
			Intent intent = new Intent();
			intent.putExtra(Constants.sDEST_KEY, "");
			setResult(Constants.sRESULT_BACK, intent);
			finish();
			return true;
		}
		return false;
	}

	/* Methods to set up the list */
	/**
	 * Runs the thread that gets the destinations for the given bus route.
	 */
	private void getDestinations() {
		if(dialogOn) {
			mProgressD = ProgressDialog.show(this, "", "Loading. Please wait...", true, false);
		}
		Thread com = new Thread() {
			public void run() {
				threadDone = false;
				mDest = mRoute.getDestinations();
				if(mDest != null) {
					Message msg = new Message();
	    	    	dataHandler.sendMessage(msg);
				} else {
					Intent intent = new Intent();
					intent.putExtra(Constants.sDEST_KEY, "");
					setResult(RESULT_OK, intent);
					finish();
				}
			}
		};
		threadDone = true;
		com.start();
	}
	
	/**
	 * Handles the completion of the thread in getDestinations,
	 */
	 private Handler dataHandler = new Handler() {
	    	@Override
	    	public void handleMessage(Message msg) {
				for(int i = 0; i < mDest.length; i++) {
					add(destinationString(mDest[i]));
				}
				refreshList();
				if(dialogOn) {
					mProgressD.dismiss();
				}
	    	}
	 };
	
	 /**
	 * Add destinations to the view. For the destinations to be seen, refreshList
	 * must be called.
	 * 
	 * @param dest		the destination to add to the view
	 */
	protected void add(String dest) {
		 HashMap<String,String> d = new HashMap<String,String>();
		 d.put("dest", dest);
		 mList.add(d);
	}
	
	/**
	 * Refreshes the list, adding any new elements that have been added to the list.
	 */
	protected void refreshList() {
		 SimpleAdapter dlist = new SimpleAdapter( 
					this, 
					mList,
					R.layout.destinationview_list,
					new String[] {"dest"},
					new int[] {R.id.dest});
		 setListAdapter(dlist);
		
	}
	
	/**
	 * Converts a String array (used because destinations from FirbiCom come as
	 * a String array) to a single String, where each element in the array is 
	 * in the String, comma separated (comma and space between each element),
	 * in the same order as the array.
	 * @param d		The String array to be converted
	 * @return a String containing each element in d in the order they appear in d, 
	 * separated by a comma and a space.
	 */
	private String destinationString(String[] d) {
    	String dest = "";
    	for(int i = 0; i < d.length-1; i++) {
    		dest+=d[i]+", ";
    	}
    	dest+=d[d.length-1];
    	return dest;
    }
    
	/**
     * Sets up the help dialog box.
     */
    public void setUpHelp() {
    	LayoutInflater li = (LayoutInflater)getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    	View v = li.inflate(R.layout.destinationview_help_dialog, null);
        
        TabHost helpTab = (TabHost)v.findViewById(R.id.tabhost);
        helpTab.setup();
        TabSpec ts = helpTab.newTabSpec("TAB_TAG_1"); 
        ts.setIndicator("Main");
        ts.setContent(R.id.destinationview_help_tab_main);
        helpTab.addTab(ts);
        TabSpec ts2 = helpTab.newTabSpec("TAB_TAG_2"); 
        ts2.setIndicator("Menu");
        ts2.setContent(R.id.destinationview_help_tab_menu);
        helpTab.addTab(ts2);
        
        mHelpD = new Dialog(this);
        Button b = (Button)v.findViewById(R.id.btnExit);
        b.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				mHelpD.dismiss();
			}
        });
    	mHelpD.setTitle("Route Help");
    	mHelpD.setContentView(v);
    	mHelpD.setCanceledOnTouchOutside(true);
    }
    
    /**
	 * Prevents the progress display from being displayed when the thread is used.
	 */
    public static void suppressDialog() {
		 dialogOn = false;
	 }

	/**
	 * Used to see if the thread in getDestinations is done
	 * 
	 * @return	true if the thread has completed
	 */
	public static boolean isThreadDone() {
    	return threadDone;
    }
}
